import React from "react";
import ReactDOM from "react-dom";
import "./index.css";

/* Lifting State Up */
/* 状态提升 */

// 通常多个组件需要反映相同的变化数据, 这时可以将共享状态提升到最近的共同父组件中
// 在React中, 将多个组件中需要共享的state向上移动到它们的最近共同父组件中, 便可实现共享state. 这就是所谓的“状态提升”

// 示例 - 创建一个用于计算水在给定温度下是否会沸腾的温度计算器

// 从名为BoilingVerdict的组件开始, 它接受celsius温度作为一个prop, 并据此打印出该温度是否足以将水煮沸的结果
function BoilingVerdict(props) {
    // celsius摄氏度
    if (props.celsius >= 100) return <p>The water would boil.</p>;
    else return <p>The water would not boil.</p>;
}
// Calculator渲染用于输入温度的input, 将值保存在this.state.temperautre, 根据当前输入值渲染BoilingVerdict
class Calculator1 extends React.Component {
    constructor(props) {
        super(props);
        this.state = { temperature: '' };
        this.handleChange = this.handleChange.bind(this);
    }
    handleChange(event) {
        this.setState({ temperature: event.target.value });
    }
    render() {
        const temperature = this.state.temperature;
        return (
            <fieldset>
                <legend>Enter temperature in Celsius</legend>
                <input
                    type="text"
                    value={temperature}
                    onChange={this.handleChange}
                />
                <BoilingVerdict celsius={parseFloat(temperature)} />
            </fieldset>
        );
    }
}
// Calculator1处理只有一个输入框的情况,
// 有一个新需求: 当有两个输入框, 输入不同单位时, 保持两个输入框的数据同步
// 首先提取出TemperatureInput组件, 添件一个scale prop, 判断输入的单位
// 此时两个TemperatureInput是分开工作的, 互相不知道互相的state, 为了共享state, 把其提升到父组件Calculator中
const scaleNames = { c: 'Celsius', f: 'Fahrenheit' };
class TemperatureInput1 extends React.Component {
    constructor(props) {
        super(props);
        this.state = { temperature: '' };
        this.handleChange = this.handleChange.bind(this);
    }
    handleChange(event) {
        this.setState({ temperature: event.target.value });
    }
    render() {
        const temperature = this.state.temperature;
        const scale = this.props.scale;
        return (
            <fieldset>
                <legend>Enter temperature in {scaleNames[scale]}</legend>
                <input
                    type="text"
                    value={temperature}
                    onChange={this.handleChange}
                />
                <BoilingVerdict celsius={parseFloat(temperature)} />
            </fieldset>
        );
    }
}
// props从父组件传来, TemperatureInput组件无法更改, 这个问题通过使用受控组件解决
// TemperatureInput接受的value和onChange(temperature&onTemperatureChange)来自父组件Calculator的props
class TemperatureInput2 extends React.Component {
    constructor(props) {
        super(props);
        this.state = { temperature: '' };
        this.handleChange = this.handleChange.bind(this);
    }
    handleChange(event) {
        // this.setState({ temperature: event.target.value });
        console.log(event.target.value);
        this.props.onTemperatureChange(event.target.value);
    }
    render() {
        // const temperature = this.state.temperature;
        const temperature = this.props.temperature;
        const scale = this.props.scale;
        return (
            <fieldset>
                <legend>Enter temperature in {scaleNames[scale]}</legend>
                <input
                    type="text"
                    value={temperature}
                    onChange={this.handleChange}
                />
            </fieldset>
        );
    }
}
class Calculator2 extends React.Component {
    constructor(props) {
        super(props);
        this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
        this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
        this.state = { temperature: '', scale: 'c' };
    }

    handleCelsiusChange(temperature) {
        this.setState({ scale: 'c', temperature });
    }

    handleFahrenheitChange(temperature) {
        this.setState({ scale: 'f', temperature });
    }

    render() {
        const scale = this.state.scale;
        const temperature = this.state.temperature;
        // 如果某些数据可以由props或state推导得出, 那么它就不应该存在于state中, 所以两个输入框的返回值不单独存储, 而是通过推导得出来
        const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
        const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;

        return (
            <div>
                <TemperatureInput2
                    scale="c"
                    temperature={celsius}
                    onTemperatureChange={this.handleCelsiusChange} />
                <TemperatureInput2
                    scale="f"
                    temperature={fahrenheit}
                    onTemperatureChange={this.handleFahrenheitChange} />
                <BoilingVerdict
                    celsius={parseFloat(celsius)} />
            </div>
        );
    }
}
// 转换函数
function toCelsius(fahrenheit) {
    return (fahrenheit - 32) * 5 / 9;
}

function toFahrenheit(celsius) {
    return (celsius * 9 / 5) + 32;
}
function tryConvert(temperature, convert) {
    const input = parseFloat(temperature);
    if (Number.isNaN(input)) {
        return '';
    }
    const output = convert(input);
    const rounded = Math.round(output * 1000) / 1000;
    return rounded.toString();
}

ReactDOM.render(
    <Calculator2 />,
    document.getElementById('root')
);